Nested p2m: use a linked list for LRU np2m selection.
authorTim Deegan <Tim.Deegan@citrix.com>
Thu, 30 Jun 2011 09:26:54 +0000 (10:26 +0100)
committerTim Deegan <Tim.Deegan@citrix.com>
Thu, 30 Jun 2011 09:26:54 +0000 (10:26 +0100)
Because the flush-all-np2ms op doesn't take the np2m lock any more
we can't reorder the p2ms in the array that it will walk.

Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
xen/arch/x86/mm/p2m.c
xen/include/asm-x86/p2m.h

index a8f18ac484742b89a4fd404b22a6254360a6d197..39acd60107555177e9533628e85c49644aa5227a 100644 (file)
@@ -73,6 +73,7 @@ static void p2m_initialise(struct domain *d, struct p2m_domain *p2m)
 {
     memset(p2m, 0, sizeof(*p2m));
     mm_lock_init(&p2m->lock);
+    INIT_LIST_HEAD(&p2m->np2m_list);
     INIT_PAGE_LIST_HEAD(&p2m->pages);
     INIT_PAGE_LIST_HEAD(&p2m->pod.super);
     INIT_PAGE_LIST_HEAD(&p2m->pod.single);
@@ -104,6 +105,7 @@ p2m_init_nestedp2m(struct domain *d)
             return -ENOMEM;
         p2m_initialise(d, p2m);
         p2m->write_p2m_entry = nestedp2m_write_p2m_entry;
+        list_add(&p2m->np2m_list, &p2m_get_hostp2m(d)->np2m_list);
     }
 
     return 0;
@@ -1048,37 +1050,16 @@ int p2m_get_mem_access(struct domain *d, unsigned long pfn,
 static struct p2m_domain *
 p2m_getlru_nestedp2m(struct domain *d, struct p2m_domain *p2m)
 {
-    int i, lru_index = -1;
-    struct p2m_domain *lrup2m, *tmp;
-
-    if (p2m == NULL) {
-        lru_index = MAX_NESTEDP2M - 1;
-        lrup2m = d->arch.nested_p2m[lru_index];
-    } else {
-        lrup2m = p2m;
-        for (i = 0; i < MAX_NESTEDP2M; i++) {
-            if (d->arch.nested_p2m[i] == p2m) {
-                lru_index = i;
-                break;
-            }
-        }
-    }
-
-    ASSERT(lru_index >= 0);
-    if (lru_index == 0) {
-        return lrup2m;
-    }
+    struct list_head *lru_list = &p2m_get_hostp2m(d)->np2m_list;
+    
+    ASSERT(!list_empty(lru_list));
 
-    /* move the other's down the array "list" */
-    for (i = lru_index - 1; i >= 0; i--) {
-        tmp = d->arch.nested_p2m[i];
-        d->arch.nested_p2m[i+1] = tmp;        
-    }
+    if ( p2m == NULL )
+        p2m = list_entry(lru_list->prev, struct p2m_domain, np2m_list);
 
-    /* make the entry the first one */
-    d->arch.nested_p2m[0] = lrup2m;
+    list_move(&p2m->np2m_list, lru_list);
 
-    return lrup2m;
+    return p2m;
 }
 
 /* Reset this p2m table to be empty */
index c39ebd2c55a91f6cb0f71a2bca1a06147404de8c..dad0f348073f9bb146d4da309379b7dd8d3c3cbb 100644 (file)
@@ -209,6 +209,12 @@ struct p2m_domain {
 #define CR3_EADDR     (~0ULL)
     uint64_t           cr3;
 
+    /* Nested p2ms: linked list of n2pms allocated to this domain. 
+     * The host p2m hasolds the head of the list and the np2ms are 
+     * threaded on in LRU order. */
+    struct list_head np2m_list; 
+
+
     /* Host p2m: when this flag is set, don't flush all the nested-p2m 
      * tables on every host-p2m change.  The setter of this flag 
      * is responsible for performing the full flush before releasing the